package graph;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;

import settings.Global;
import text.ReadTextFile;

/**
 * Graph with method to get outgoing links for articles
 * 
 * @author Jonathan
 * 
 */
public class GraphFile
{
    private ArrayList<String> titles;
    private ArrayList<Integer> startingFilesNumbers;
    private String directoryForSmallFiles;
    private HashMap<Integer, Boolean> marked;
    private HashMap<Integer, Integer> edgeTo;

    /**
     * Initializes an ArrayList of titles and breaks down the large file into smaller files.
     * 
     * @param createDirectory
     */
    public GraphFile(boolean createDirectory)
    {
	directoryForSmallFiles = Global.smallFileLocation;

	// Do I need to do the work to create the files?
	if (createDirectory)
	    startingFilesNumbers = ReadTextFile.bigFile_smallFile(Global.linksFileLocation, Global.smallFileLocation);
	else
	    startingFilesNumbers = ReadTextFile.readStartingNumbers();
	// TODO - make this better

	titles = ReadTextFile.titles_to_list(Global.titleFileLocation, Global.numWikiPages);
    }

    /**
     * Given a page number, return an ArrayList of outgoing links from the files this will read
     * 
     * @param pageNum
     *            Page number of page to get outgoing links from.
     * @return ArrayList of page numbers of outgoing links.
     */
    public ArrayList<Integer> getOutgoingLinks(int pageNum)
    {
	// get the file that the OutgoingLinks are in
	// binary search
	int fileNum = GraphHelper.binarySearch(startingFilesNumbers, pageNum);
	String file = Global.smallFileLocation + Integer.toString(fileNum) + ".txt";
	int textReadInt;
	String textReadString;

	// perform a sequential search on the file
	try
	{
	    // read in the file
	    FileInputStream fstream = new FileInputStream(file);
	    DataInputStream in = new DataInputStream(fstream);
	    BufferedReader br = new BufferedReader(new InputStreamReader(in));
	    StringTokenizer st;
	    String strLine;
	    String temp1;
	    int temp2;

	    // Read File Line By Line
	    while ((strLine = br.readLine()) != null)
	    {// get line
		st = new StringTokenizer(strLine, ": "); // tokenize

		textReadString = st.nextToken();

		if (textReadString == null)
		{// null
		    return new ArrayList<Integer>();
		}
		else
		{// look at ints
		    textReadInt = Integer.parseInt(textReadString);// convert

		    if (textReadInt < pageNum)
		    {
			// go on
		    }
		    else if (textReadInt == pageNum)
		    {
			ArrayList<Integer> ali = new ArrayList<Integer>();
			while (st.hasMoreTokens())
			{
			    temp1 = st.nextToken();
			    if (temp1 != null)
			    {
				temp2 = Integer.parseInt(temp1);
				ali.add(temp2);// add to the array list
			    }
			}
			return ali;// - finished
		    }
		    else
		    {
			// quit, gone far
			return new ArrayList<Integer>();
		    }

		}
	    }
	    in.close();// Close the input stream
	} catch (Exception e)
	{// Catch exception if any
	    System.err.println("Error: " + e.getMessage());
	    return new ArrayList<Integer>();
	}
	return new ArrayList<Integer>();// should not reach here
    }

    /**
     * This function returns the corresponding page name
     * 
     * @param pageNum
     *            Page number
     * @return Page name
     */
    public String getPageName(int pageNum)
    {
	// TODO - error checks
	String pageName = titles.get(pageNum);
	pageName = pageName.replace("_", " ");

	return pageName;
    }

    /**
     * Given a article name, return its pageNum
     * 
     * @param pageName
     *            Page title of article
     * @return Page number of article
     */
    public int getPageNum(String pageName)
    {
	// replace " " with "_"
	pageName = pageName.replace(" ", "_");

	int indexA = titles.indexOf(pageName);
	return indexA;
    }
}
